import Style from './Style.js';


// 储存全局消息状态
const globalMessageStatus = {
    msg: true, // 为true时表示可以新建消息了
    container: null, // 上一个消息的container对象
    timer: [],
};

let dblFlag = 0;


export default class Util {
    constructor() { };

    /**
    * 给传入的数字前加上零，传入的不是数字或无法转换为数字则返回0
    * 
    * @param {number} target 
    * @param {number} total 
    * @return {string} 
    * 
    */
    static addZero(target, total) {
        target = isNaN(Number(target)) ? 0 : Number(target);
        target = target + '';
        if (target.length < total) {
            for (let i = 0; i < total - target.length + 1; i++) {
                target = '0' + target;
            }
            return target;
        } else {
            return target;
        }
    }

    // 判断浏览器种类 退出全屏
    static exitFullscreen() {
        try {
            if (document.exitFullscreen) {
                document.exitFullscreen()
            } else if (document.mozCancelFullScreen) {
                document.mozCancelFullScreen()
            } else if (document.webkitExitFullscreen) {
                document.webkitExitFullscreen()
            }
        } catch {
            Util.globalMessage('退出全屏失败，请使用F11退出全屏！', 'error');
        }
    }

    // 必须用户事件触发（可以是鼠标事件，键盘事件等）
    // 某个元素全屏
    // launchFullscreen(dom) 
    // 整个网页全屏
    // launchFullscreen(document.documentElement)
    static launchFullscreen(element) {
        if (element.requestFullscreencreen) {
            element.requestFullScreen()
        } else if (element.mozRequestFullScreen) {
            element.mozRequestFullScreen()
        } else if (element.webkitRequestFullScreen) {
            element.webkitRequestFullScreen()
        } else if (element.msRequestFullScreen) {
            element.msRequestFullScreen()
        }
    }

    static isFullscreenForNoScroll() {
        const explorer = window.navigator.userAgent.toLowerCase();
        if (explorer.indexOf('chrome') > 0) {//webkit
            if (document.body.scrollHeight === window.screen.height && document.body.scrollWidth === window.screen.width) {
                return true;
            } else {
                return false;
            }
        } else {//IE 9+  fireFox
            if (window.outerHeight === window.screen.height && window.outerWidth === window.screen.width) {
                return true;
            } else {
                return false;
            }
        }
    }

    static isFullscreen() {
        return document.fullscreenElement ||
            document.msFullscreenElement ||
            document.mozFullScreenElement ||
            document.webkitFullscreenElement || false;
    }

    /**
     * 倒计时
     * 
     * @param {string} endTime 
     * @return {object} { day: d, hour: h, minute: m, second: s, }
     * 
    */
    static coundDown(endTime) {
        //获取当前时间  
        const date = new Date();
        const now = date.getTime();
        //设置截止时间  

        // const str = "2020/12/26 00:00:00";
        const endDate = new Date(endTime);
        const end = endDate.getTime();

        //时间差  
        let leftTime = end - now;
        //定义变量 d,h,m,s保存倒计时的时间  
        let d, h, m, s;
        if (leftTime >= 0) {
            d = Math.floor(leftTime / 1000 / 60 / 60 / 24) || 0;
            h = Math.floor(leftTime / 1000 / 60 / 60 % 24) || 0;
            m = Math.floor(leftTime / 1000 / 60 % 60) || 0;
            s = Math.floor(leftTime / 1000 % 60) || 0;
        } else {
            d, h, m, s = 0;
        }

        return {
            day: d,
            hour: h,
            minute: m,
            second: s,
        };
    }

    // static appendToElem(tagName, targetElem, content, attr) {
    //     const attrs = attr || {};
    //     const elem = document.createElement(tagName);
    //     for (const attr in attrs) {
    //         elem.setAttribute(attr, attrs[attr]);
    //     }
    //     elem.innerHTML = content;
    //     targetElem.appendChild(elem);
    //     console.log(`Append ${elem.tagName} to ${targetElem.tagName} succeed!`);
    // }

    // static appendToHead(tagName, content, attr) {
    //     const head = document.head || document.getElementsByTagName('head')[0];
    //     appendToElem(tagName, head, content, attr);
    // }

    // static appendToBody(tagName, content, attr) {
    //     const body = document.body || document.getElementsByTagName('body')[0];
    //     appendToElem(tagName, body, content, attr);
    // }

    // 将驼峰属性名转为短横线属性名
    static toLineAttr(attr) {
        return attr.replace(/([A-Z])/g, (all, letter) => {
            return `-${letter.toLowerCase()}`;
        });
    };

    static sleep(fn, time) {
        const timer = setTimeout(function () {
            fn();
        }, time);
        return timer;
    }

    static _buildMessage(msg, type) {

        const container = document.createElement('div');
        container.innerHTML = `
            <style>
                ${Style.globalMessage()}
            </style>
            <div class="global-message-${type.toLowerCase()}">
                <div class="left-box"></div>
                <span class="msg-text">${msg}</span>
                <div class="right-box"></div>
            </div>`;
        container.setAttribute('class', 'message-container animated bounceIn');
        document.body.appendChild(container);

        globalMessageStatus.container = container;
        const outTimer = setTimeout(() => {
            container.setAttribute('class', 'message-container animated fadeOut');
            const innerTimer = Util.sleep(() => {
                container.parentNode.removeChild(container);
                globalMessageStatus.msg = true;
            }, 800);
            globalMessageStatus.timer.push(innerTimer);
        }, 2000);
        globalMessageStatus.timer.push(outTimer);
    }

    /**
     *
     *
     * @static 
     * @param {string} msg
     * @param {string} type  'error'|| 'normal'
     * @memberof Util
     */
    static globalMessage(msg, type) {
        type = type || 'normal';

        if (globalMessageStatus.msg) {
            globalMessageStatus.msg = false;
            Util._buildMessage(msg, type);
        } else {
            for (let i = 0; i < globalMessageStatus.timer.length; i++) {
                clearTimeout(globalMessageStatus.timer[i]);
            }
            globalMessageStatus.timer.length = 0;
            globalMessageStatus.container.parentNode.removeChild(globalMessageStatus.container);
            Util._buildMessage(msg, type);
        }
    }

    //随机生成最大值不超过max的整数
    static randInt(max) {
        return Math.floor(Math.random() * 100000 % max);
        //random生成0~1之间的随机数
    }

    //生成随机颜色
    static randColor() {
        const r = randInt(256);   //取值范围均为0~255;
        const g = randInt(256);
        const b = randInt(256);
        return 'rgb(' + r + ',' + g + ',' + b + ')';
    }

    /**
     * 排除event.target为目标元素的子元素的情况
     * 返回真正希望的target
     *
     * @static
     * @param {Event} event
     * @param {String[]} args  第一个元素是目标元素的tagName，之后的是目标元素的子元素的tagName
     * @return { HTMLElement | Undefined } 
     * @memberof Util
     */

    static getTarget(event, ...args) {
        if (event.target.tagName === args[0]) {
            return event.target;
        }

        for (let i = 1; i < args.length; i++) {
            if (event.target.tagName === args[i]) {

                event.stopPropagation();

                // 去除重复触发事件
                // if (bubbleCache == event.target.parentElement) {
                //     return null;
                // }
                // bubbleCache = event.target.parentElement;
                return event.target.parentElement;
            }
        }

        return null;
    }

    static timer() {
        let _on = false;
        let _timer = null;
        let _func = null;
        let _interval = 0;

        function _start() {
            if (_on) {
                _func.call(null);
                _timer = window.setTimeout(_start, _interval);
            }
        }

        return {
            set(func, interval) {
                _func = func;
                _interval = interval;
                if (!_on) {
                    _on = true;
                    _start();
                } else {
                    window.clearTimeout(_timer);
                    _on = true;
                    _start();
                }
            },
            clear() {
                _on = false;
                _timer = null;
                _func = null;
                _interval = 0;
            },
        }
    }

    static getStyle(elem, attr) {
        if (elem.currentStyle) {   //IE浏览器
            return elem.currentStyle[attr];
        } else {    //chrome、firefox等浏览器
            return getComputedStyle(elem, null)[attr];
        }
    }

    static animate(elem, json, callback, spd) {
        if (elem.timer) {
            elem.timer.clear();
        }

        elem.timer = Util.timer();

        const result = JSON.parse(JSON.stringify(json));

        for (let attr in json) {
            result[attr] = false;
        }

        function setWithUnit(attr, unit, ...args) {

            if (result[attr]) {
                return;
            }

            let currentStyle = parseFloat(Util.getStyle(elem, attr));
            let speed;
            if (attr == args[0] || attr == args[1] || attr == args[2]) {
                if (unit === 'vw') {
                    currentStyle = currentStyle * 100 / document.body.clientWidth;
                } else if (unit === 'vh') {
                    currentStyle = currentStyle * 100 / document.body.clientHeight;
                }
                speed = (json[attr] - currentStyle) / 10;
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
                speed = speed > 0 ? spd || speed : -spd || speed;
                if (speed > 0 && currentStyle + speed >= json[attr]) {
                    elem.style[attr] = json[attr] + unit;
                    result[attr] = true;
                } else if (speed < 0 && currentStyle + speed <= json[attr]) {
                    elem.style[attr] = json[attr] + unit;
                    result[attr] = true;
                } else {
                    elem.style[attr] = (currentStyle + speed) + unit;
                    result[attr] = false;
                }
            }
        }

        elem.timer.set(() => {
            for (let attr in json) {
                let currentStyle = parseFloat(Util.getStyle(elem, attr));

                if (isNaN(currentStyle)) {
                    elem.style[attr] = json[attr];
                    result[attr] = true;
                }

                let speed;
                if (attr == 'opacity') {
                    speed = json[attr] - currentStyle > 0 ? 0.1 : -0.1;
                    if (speed > 0 && currentStyle + speed >= json[attr]) {
                        elem.style[attr] = json[attr];
                        result[attr] = true;
                    } else if (speed < 0 && currentStyle + speed <= json[attr]) {
                        elem.style[attr] = json[attr];
                        result[attr] = true;
                    } else {
                        elem.style[attr] = currentStyle + speed;
                        result[attr] = false;
                    }
                }

                setWithUnit(attr, 'vw', 'width', 'left', 'right');
                setWithUnit(attr, 'vh', 'height', 'top', 'bottom');
            }

            let flag = true;
            for (let attr in result) {
                if (result[attr] == false) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                elem.timer.clear();
                callback && callback();
            }
            // console.log('动画定时器正在运行！！！');
        }, 32);
    }

    static doubleclick(elem, onsingle, ondouble) {
        if (dblFlag) {
            dblFlag = 1;
            setTimeout(function () {
                if (dblFlag) {
                    onsingle(elem);
                }
                dblFlag = 0;
            }, 300);
        } else {
            dblFlag = 0;
            ondouble(elem);
        }
    }

    static insertAfter(parent, child, refChild) {
        const elem = refChild.nextSibling;
        parent.insertBefore(child, elem);
    }

    static prependChild(parent, child) {
        const elem = parent.firstChild;
        parent.insertBefore(child, elem);
    }

    static uid() {
        return new Date().getTime() + '' + (Util.randInt(996) * 996 * 120);
    }

    static getSrcs(html) {
        const pattern = /<script(?:(?:\s|.)+?)src=[\"\'](.+?)[\"\'](?!\<)(?:(?:\s|.)*?)(?:(?:\/\>)|(?:\>\s*?\<\/script\>))/g;

        const srcs = [];
        let match;
        while ((match = pattern.exec(html)) !== null) {
            srcs.push(match[1]);
        }
        return srcs;
    }

    static parseQueryString(url){
        var arr;
        var res = {};
        //#符号之后的值称为hash，都不会加到request请求中去
        url = url.split('#')[0];
        //获取queryString 第一个?号后面的全是查询字符串
        arr = url.split('?');
        arr.shift();
        var queryStr = arr.join('?');
        //查询字符串为空直接返回 避免出现这样的返回值{"":""}
        if (queryStr.trim().length == 0){
            return res;
        }
    
        //获取参数
        arr = queryStr.split('&');
        for (var i = 0; i <  arr.length; i++) {
            var itemArr = arr[i].split('=');
            //第一个=号之前的是name 后面的全是值
            var name = itemArr.shift();
            var value = itemArr.join('=');
            res[name] = value;
        }
        return res;
    }
}